package com.wuliang.generate.common.sharding.pool;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.wuliang.generate.common.sharding.domain.Sharding;
import io.shardingjdbc.core.api.ShardingDataSourceFactory;
import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.api.config.TableRuleConfiguration;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

public class DefaultShardingDataSourcePool implements ShardingDataSourcePool {

    public static final Map<String, Sharding> SHARDING_LIST = new LinkedHashMap<>();
    public static final Map<String, DataSource> SHARDING_DATASOURCE_MAP = new LinkedHashMap<>();
    public static final List<TableRuleConfiguration> databaseRuleConfigs = new LinkedList<>();
    private static final Properties properties = new Properties();

    static {
        properties.setProperty("sql.show", "true");
    }

    public DataSource initShardingDataSource() throws SQLException {
        for (Map.Entry<String, Sharding> shardingEntry : SHARDING_LIST.entrySet()) {
            createDataSource(shardingEntry.getKey(), shardingEntry.getValue());
        }
        return ShardingDataSourceFactory.createDataSource(SHARDING_DATASOURCE_MAP, initRuleConfig(), new LinkedHashMap<>(), properties);
    }

    public void createDataSource(String keyword, Sharding sharding) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setPassword(sharding.getPassword());
        dataSource.setUsername(sharding.getUsername());
        dataSource.setUrl(sharding.getUrl());
        SHARDING_DATASOURCE_MAP.put(keyword, dataSource);
        for (String tableNames : sharding.getTableNamesInDatabase()) {
            TableRuleConfiguration tableRuleConfiguration = new TableRuleConfiguration();
            tableRuleConfiguration.setLogicTable(tableNames);
            tableRuleConfiguration.setActualDataNodes(sharding.getDatabaseName());
        }
    }

    public void createDataSourceIntoSharding(String keyword) throws SQLException {
        ShardingDataSource dataSource = (ShardingDataSource) SpringUtil.getBean(DataSource.class);
        createDataSource(keyword, SHARDING_LIST.get(keyword));
        dataSource.renew(initRuleConfig().build(SHARDING_DATASOURCE_MAP), properties);
    }

    public ShardingRuleConfiguration initRuleConfig() {
        ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
        shardingRuleConfiguration.setTableRuleConfigs(databaseRuleConfigs);
        return shardingRuleConfiguration;
    }

}
